{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "parameters_content = '''\n",
    "#include <stdio.h>\n",
    "#include \"include/gemmini.h\"\n",
    "\n",
    "#define LEN(arr) ((int) (sizeof (arr) / sizeof (arr[0])))\n",
    "\n",
    "'''\n",
    "SYS_DIM=32\n",
    "batch_size=32\n",
    "input_dim=3036\n",
    "param_file_name=\"parameters8.h\"\n",
    "test_file_name=\"test8.c\"\n",
    "if(batch_size%SYS_DIM !=0):\n",
    "    print('please use a batch size of SYS_DIM')\n",
    "    exit(1)   \n",
    "#layers = [input_dim,2500,2000,1500,1000,500,10]\n",
    "layers=[input_dim,4554,3036]\n",
    "mlp='// batch size: ' + str(batch_size) +'\\n'\n",
    "mlp+='// before zeropad: '\n",
    "for l in layers:\n",
    "    mlp=mlp+str(l)+'x'\n",
    "    \n",
    "parameters_content = parameters_content+mlp[:-1]+'\\n'\n",
    "for i,l in enumerate(list(layers)):\n",
    "    layers[i] = int((l+SYS_DIM-1)/SYS_DIM)*SYS_DIM\n",
    "    \n",
    "mlp='// after zeropad: '\n",
    "for l in layers:\n",
    "    mlp=mlp+str(l)+'x'\n",
    "parameters_content = parameters_content+mlp[:-1]+'\\n'\n",
    "\n",
    "input_mat = 'elem_t input_mat[{0}][{1}] row_align(1)= '.format(batch_size,layers[0]) + '{0};\\n'\n",
    "parameters_content = parameters_content+input_mat;\n",
    "\n",
    "matmuls = []\n",
    "for i,(l1,l2) in enumerate(zip(layers[:-1],layers[1:])):\n",
    "    matrix = 'elem_t weights'+str(i)+'['+str(l1)+']'+'['+str(l2)+'] row_align(1)= {0};\\n'\n",
    "    parameters_content = parameters_content+matrix\n",
    "    inter_results = 'elem_t inter_results'+str(i)+'['+str(batch_size)+']'+'['+str(l2)+'] row_align(1)= {0};\\n'\n",
    "    parameters_content = parameters_content+inter_results\n",
    "    if i==0:\n",
    "        matmuls.append(('input_mat',batch_size,'weights'+str(i),l1,'inter_results'+str(i),l2))\n",
    "    else:\n",
    "        matmuls.append(('inter_results'+str(i-1),batch_size,'weights'+str(i),l1,'inter_results'+str(i),l2))\n",
    "\n",
    "f = open(param_file_name, \"w\")\n",
    "f.write(parameters_content)\n",
    "f.close()\n",
    "\n",
    "test_content= '''\n",
    "\n",
    "#include <stdio.h>\n",
    "#include <string.h>\n",
    "#include <stdbool.h>\n",
    "#include <sys/mman.h>\n",
    "#include \"include/gemmini.h\"\n",
    "#include ''' +'\"'+param_file_name+'\"'+ '''\n",
    "\n",
    "#define verbose(layer_num,old_C,filter,C) printf(\"layer %d: operand %d %d filter %d %d result %d %d\\\\n\", layer_num, LEN(old_C),LEN(old_C[0]),LEN(filter),LEN(filter[0]),LEN(C),LEN(C[0]));\n",
    "\n",
    "static void tiled_matmul_compare(size_t DIM_I, size_t DIM_J, size_t DIM_K,\n",
    "        elem_t A[DIM_I][DIM_K], elem_t B[DIM_K][DIM_J], acc_t D[DIM_I][DIM_J],\n",
    "        elem_t C[DIM_I][DIM_J], int no_bias, int act, int shift, int relu6_shift,\n",
    "        enum tiled_matmul_type_t tiled_matmul_type,\n",
    "        bool compare, char * layer_name)\n",
    "{\n",
    "    if (compare)\n",
    "        printf(\"%s: gemmini\\\\n\", layer_name);\n",
    "    tiled_matmul_option(DIM_I, DIM_J, DIM_K,\n",
    "        A, B, D, C, no_bias, act, shift, relu6_shift,\n",
    "        tiled_matmul_type);\n",
    "\n",
    "    if (compare) {\n",
    "        printf(\"%s: CPU\\\\n\", layer_name);\n",
    "        elem_t gold[DIM_I][DIM_J];\n",
    "        tiled_matmul_option(DIM_I, DIM_J, DIM_K,\n",
    "            A, B, D, gold, no_bias, act, shift, relu6_shift,\n",
    "            CPU);\n",
    "\n",
    "        printf(\"%s: comparing\\\\n\", layer_name);\n",
    "        for (size_t i = 0; i < DIM_I; i++) {\n",
    "            for (size_t j = 0; j < DIM_J; j++) {\n",
    "                if (C[i][j] != gold[i][j]) {\n",
    "                    printf(\"Layer calculated incorrectly: %s\\\\n\", layer_name);\n",
    "                    exit(1);\n",
    "                }\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "int main (int argc, char * argv[]) {\n",
    "#ifndef BAREMETAL\n",
    "    if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {\n",
    "      perror(\"mlockall failed\");\n",
    "      exit(1);\n",
    "    }\n",
    "#endif\n",
    "\n",
    "    matmul_flush(0);\n",
    "\n",
    "    enum tiled_matmul_type_t tiled_matmul_type;\n",
    "    if (argc < 2) {\n",
    "        // printf(\"usage: %s matmul_option\\\\n  matmul_option may be 'os', 'ws', or cpu'\\\\n\");\n",
    "        // exit(0);\n",
    "        tiled_matmul_type = OS;\n",
    "    } else if (strcmp(argv[1], \"cpu\") == 0) {\n",
    "        tiled_matmul_type = CPU;\n",
    "    } else if (strcmp(argv[1], \"os\") == 0) {\n",
    "        tiled_matmul_type = OS;\n",
    "    } else if (strcmp(argv[1], \"ws\") == 0) {\n",
    "        tiled_matmul_type = WS;\n",
    "    }\n",
    "\n",
    "    bool compare;\n",
    "    if (argc < 3) {\n",
    "        compare = false;\n",
    "    } else if (strcmp(argv[2], \"compare\") == 0) {\n",
    "        compare = true;\n",
    "    } else {\n",
    "        printf(\"Unknown command-line argument\\\\n\");\n",
    "        exit(1);\n",
    "    }\n",
    "\n",
    "\n",
    "'''\n",
    "test_content =  test_content + '    uint64_t cycles['+str(len(layers)-1)+']={0};\\n'\n",
    "test_content =  test_content + '    uint64_t start,end;\\n'\n",
    "test_content =  test_content + '    start = read_cycles();'\n",
    "for m,(A,a,weight,w,C,c) in enumerate(matmuls):\n",
    "    test_content +='\\n\\n    /* matmul number: {0} */\\n\\n'.format(str(m))\n",
    "    test_content +='    tiled_matmul_compare({0}, {1}, {2},    // dimensions\\n'.format(a,c,w)\n",
    "    test_content +='    {0}, {1}, NULL, {2},      // addresses\\n'.format(A,weight,C)\n",
    "    test_content +='    1, RELU, 0, 0,              // no_bias, act, shift, r6_shift\\n'\n",
    "    test_content +='    tiled_matmul_type, compare, \"layer_'+str(m)+'\");\\n'\n",
    "    test_content +='    // verbose({0},{1},{2},{3})\\n'.format(m,A,weight,C)\n",
    "    test_content +='    /* end of matmul number: {0} */\\n\\n'.format(str(m))\n",
    "    test_content +='    end = read_cycles();\\n'\n",
    "    test_content +='    cycles['+str(m)+'] = end-start;\\n'\n",
    "    test_content +='    start = end;\\n'\n",
    "\n",
    "test_content +='''\n",
    "    uint64_t overall_cycles = 0;\n",
    "    for(int cyc = 0; cyc < '''+str(len(layers)-1)+''' ; cyc++){\n",
    "        overall_cycles += cycles[cyc];\n",
    "        printf(\"Cycles taken in layer %d: %llu\\\\n\", cyc,cycles[cyc]);\n",
    "    }\n",
    "    printf(\"Overall cycles taken: %llu\\\\n\",overall_cycles);\n",
    "\\n\n",
    "    return 0;\n",
    "}\\n\n",
    "''' \n",
    "\n",
    "f = open(test_file_name, \"w\")\n",
    "f.write(test_content)\n",
    "f.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
